package com.xhu.service.impl;

import com.xhu.dao.MissionMapper;
import com.xhu.entity.Mission;
import com.xhu.service.HideService;
import com.xhu.util.HideHtml;
import com.xhu.util.Hider;
import com.xhu.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class HideServiceImpl implements HideService {

    @Autowired
    private MissionMapper missionMapper;

    @Override
    public String hideMessageByAttr(String userInfo, String missionName, String path, String encryptContext) throws IOException {
        //读取HTML文件内容
        List<StringBuilder> context = HideHtml.getHtmlContents(path, true);

        //获取加入了密文长度信息的二进制字符串
        Queue<Character> messageQue = HideHtml.getMessage(encryptContext, "1");

        //遍历HTML代码使用正则表达式寻找属性等式
        for (StringBuilder s: context) {
            String reg="[a-z]+=['|\"].+['|\"]";
            Pattern p=Pattern.compile(reg);
            Matcher m=p.matcher(s);
            while(m.find()){
                String string = m.group().split("=")[0];
                String hidemes = String.valueOf(messageQue.poll()+messageQue.poll());

                //当隐藏的信息为01时
                if(hidemes.equals("01")){
                    //letterSum(string)为偶数，IsCaptail(string)为单引号可以隐藏01
                    if(!(Utils.letterSum(string) % 2 == 0 && Utils.IsCaptail(string)) == true){
                        if(Utils.letterSum(string) % 2 == 1){
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                        if(Utils.IsCaptail(string) == false){
                            string = string.replaceAll("\"","'");
                        }
                        if((Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == false){
                            string = string.replaceAll("\"","'");
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                    }
                }

                //当隐藏的信息为00时
                if(hidemes.equals("00")){
                    //letterSum(string)为偶数，IsCaptail(string)为双引号可以隐藏00
                    if(!(Utils.letterSum(string) % 2 == 0 && Utils.IsCaptail(string)) == false){

                        if(Utils.letterSum(string) % 2 == 1){
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                        if(Utils.IsCaptail(string) == true){
                            string = string.replaceAll("'","\"");
                        }
                        if((Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == true){
                            string = string.replaceAll("'","\"");
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }

                    }
                }

                //当隐藏的信息为11时
                if(hidemes.equals("11")){
                    //letterSum(string)为奇数，IsCaptail(string)为单引号可以隐藏11
                    if(!(Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == false){

                        if(Utils.letterSum(string) % 2 == 0){
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                        if(Utils.IsCaptail(string) == true){
                            string = string.replaceAll("'","\"");
                        }
                        if((Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == true){
                            string = string.replaceAll("'","\"");
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                    }

                }

                //当隐藏的信息为10时
                if(hidemes.equals("10")){
                    //letterSum(string)为奇数，IsCaptail(string)为双引号可以隐藏10
                    if(!(Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == true){

                        if(Utils.letterSum(string) % 2 == 0){
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                        if(Utils.IsCaptail(string) == false){
                            string = string.replaceAll("\"","'");
                        }
                        if((Utils.letterSum(string) % 2 == 1 && Utils.IsCaptail(string)) == false){
                            string = string.replaceAll("\"","'");
                            string = string.substring(0,0)+ string.substring(1,string.length()-2) + " " + string.substring(0,0);
                        }
                    }

                }

                s.replace(0,s.length(), string);
            }
        }

        FileOutputStream fileOutputStream = new FileOutputStream(path+".result");
        for (StringBuilder s: context) {
            fileOutputStream.write(s.toString().getBytes(StandardCharsets.UTF_8));
            fileOutputStream.write("\n".getBytes(StandardCharsets.UTF_8));
        }

        fileOutputStream.close();
        return "true";
    }

    @Override
    public String hideMessage(String userAccount, String missionName,String fileName, String message, String type) throws IOException {
        //获取html文件内容
        List<StringBuilder> context = null;
        context = HideHtml.getHtmlContents(fileName, true);

        //获取加入了密文长度信息的二进制字符串
        Queue<Character> messageQue = HideHtml.getMessage(message, type);
        if(type.equals("0")){
            //建立信息隐藏对象
            Hider hider = new Hider(context);
            //在做信息隐藏前先获取“=”数量，并且判断其数量是否能足够隐藏信息
            int equalCount = hider.getEqualCount();
            int messLen = messageQue.size();
            if(equalCount*2 < messLen){
                return "html文件包含的等号数不够隐藏信息,至少需要"+ (messLen+1)/2 +"个等号";
            }

            if((1<<HideHtml.LEN)-1 < messLen){
                return "需要隐藏的信息太长,请精简";
            }

            //进行信息隐藏
            context = hider.hide(messageQue);
        }else{
            for (StringBuilder htmlContent : context) {
                StringBuilder temp = new StringBuilder(htmlContent.toString());
                boolean isOver = false;
                boolean isFirstWord = true;
                //正则表达式匹配属性值
                String reg="(?<=[a-z|\\-|_]=)['|\"].+?['|\"]";
                Pattern p=Pattern.compile(reg);
                Matcher m=p.matcher(temp);
                int pos = 0;
                while (m.find()){
                    String attr = m.group();

                    Character first = messageQue.poll();
                    if (first == null){
                        isOver = true;
                        break;
                    }

                    //属性值长度为偶数并且加密内容为1
                    if(Utils.letterSum(attr)%2==0 && first=='1'){
                        htmlContent.insert(m.end()+pos-1, ' ');
                        pos++;
                    }
                    //属性值长度为奇数并且加密内容为0
                    else if(Utils.letterSum(attr)%2==1 && first=='0'){
                        htmlContent.insert(m.end()+pos-1, ' ');
                        pos++;
                    }

                    Character second = messageQue.poll();
                    if(second == null){
                        isOver = true;
                        break;
                    }

                    int startPos = isFirstWord? m.start():m.start()+pos;
                    //属性值引号为双引号并且加密内容为1
                    if (Utils.IsCaptail(attr)==true && second=='1'){
                        htmlContent.setCharAt(startPos, '\'');
                        htmlContent.setCharAt(m.end()-1+pos, '\'');
                    }
                    //属性值引号为单引号并且加密内容为0
                    else if (Utils.IsCaptail(attr)==false && second=='0'){
                        htmlContent.setCharAt(startPos, '\"');
                        htmlContent.setCharAt(m.end()-1+pos, '\"');
                    }

                    isFirstWord = false;
                }

                if (isOver){
                    break;
                }
            }
        }


        //将过后的内容转存为文件
        FileOutputStream fileOutputStream = new FileOutputStream(fileName+".result");
        for (StringBuilder s: context) {
            fileOutputStream.write(s.toString().getBytes(StandardCharsets.UTF_8));
            fileOutputStream.write("\n".getBytes(StandardCharsets.UTF_8));
        }

        fileOutputStream.close();

        //已经含有隐藏信息的文件建立好之后，在数据库中插入mission记录
        Mission mission = new Mission(null, userAccount, missionName, fileName);
        missionMapper.insertSelective(mission);

        return "true";
    }

    @Override
    public boolean checkMission(String userAccount, String missionName) {
        boolean result = false;

        Integer id = missionMapper.selectByUserAccMissionName(userAccount, missionName);

        if(id != null){
            result = true;
        }

        return result;
    }
}
